package sample.tree.node.expr;

import java.util.*;
import sample.tree.node.Node;
import sample.tree.Context;
import sample.tree.visitor.ASTPrinter;
import sample.tree.visitor.Visitor;
import sample.tree.visitor.VoidVisitor;
import static sample.tree.util.Util.*;
import sample.tree.node.expr.Expr;

public final class Div extends Expr {

	private final Expr lhs;
	private final Expr rhs;
	private final int hashCode;  // cache

	public static Expr get(
			final Context context,
			final Expr lhs,
			final Expr rhs)
	{
		return context.intern(
			new Div(
					lhs,
					rhs));
	}

	private Div(
			final Expr lhs,
			final Expr rhs)
	{
		this.lhs = lhs;
		this.rhs = rhs;
		this.hashCode = hashCodeImpl();  // cache
	}

	public Expr getLhs() {
		return lhs;
	}

	public Expr getRhs() {
		return rhs;
	}

	@Override
	public void visit(final VoidVisitor v) {
		v.inDiv(this);
	}

	@Override
	public <TExpr>
	TExpr visit(
		final Visitor<TExpr> v)
	{
		return v.inDiv(this);
	}

	@Override
	public boolean equals(final Object rhs) {
		if(this == rhs)
			return true;
		if(rhs instanceof Div)
			return equalsImpl((Div)rhs);
		return false;
	}

	private boolean equalsImpl(
			final Div rhs0)
	{
		return eq(lhs, rhs0.lhs)
		    && eq(rhs, rhs0.rhs);
	}

	@Override
	public int hashCode() {
		return hashCode;
	}

	private int hashCodeImpl() {
		int hash = 17;
		hash += hash(lhs);
		hash *= 31;
		hash += hash(rhs);
		return hash;
	}

	@Override
	protected int compareToImpl(
			final Expr rhs)
	{
		return compareToImpl((Div)rhs);
	}

	private int compareToImpl(
			final Div rhs0)
	{
		int cmp;
		cmp = cmp(lhs, rhs0.lhs);
		if(cmp != EQ) return cmp;
		cmp = cmp(rhs, rhs0.rhs);
		if(cmp != EQ) return cmp;
		return EQ;
	}

	@Override
	public int ordinal() {
		return 3;
	}

	@Override
	public String toString() {
		return ASTPrinter.toString(this);
	}
}
